/**
 * 
 */
package cagt.tools;

import java.util.AbstractSequentialList;
import java.util.ArrayList;
import java.util.ListIterator;

import cagt.tools.exceptions.LimitExceededException;

/**
 * List of limited size. Based on ArrayList.
 * 
 * @author Konrad
 * 
 */
public class LimitedList<T> extends AbstractSequentialList<T> implements
		LimitedCollection<T> {
	private ArrayList<T> internal;
	private int limit;

	/**
	 * Standard constructor initializing the limit.
	 */
	public LimitedList(int limit) {
		if (limit < 0) {
			throw new IllegalArgumentException(
					"Limit must be greater or equal 0.");
		}
		this.limit = limit;
		this.internal = new ArrayList<T>(getLimit());
	}

	public int getLimit() {
		return limit;
	}

	@Override
	public ListIterator<T> listIterator(int location) {
		return new LimitedListIterator(location);
	}

	@Override
	public int size() {
		return internal.size();
	}

	private class LimitedListIterator implements ListIterator<T> {

		private ListIterator<T> internalIterator;

		public LimitedListIterator(int location) {
			internalIterator = internal.listIterator(location);
		}

		public void add(T object) {
			if (size() + 1 > getLimit()) {
				throw new LimitExceededException(getLimit());
			}
			internalIterator.add(object);
		}

		public boolean hasNext() {
			return internalIterator.hasNext();
		}

		public boolean hasPrevious() {
			return internalIterator.hasPrevious();
		}

		public T next() {
			return internalIterator.next();
		}

		public int nextIndex() {
			return internalIterator.nextIndex();
		}

		public T previous() {
			return internalIterator.previous();
		}

		public int previousIndex() {
			return internalIterator.previousIndex();
		}

		public void remove() {
			internalIterator.remove();
		}

		public void set(T object) {
			internalIterator.set(object);
		}

	}

	public boolean isFull() {
		return size() == getLimit();
	}
}
